# https://www.cnblogs.com/cangqinglang/p/14915959.html
"""
这个函数可以被Series对象调用，也可以被DataFrame对象调用，这个函数主要是用来做移动计算的。

举个栗子，
    假设我们有10天的销售额，我们想每三天求一次总和，
    比如第五天的总和就是 第三天 + 第四天 + 第五天 的销售额之和，这个时候我们的rolling函数就派上用场了。
"""
import pandas as pd


# .rolling()函数又叫移动窗口函数，此函数可以应用于一系列数据，指定参数window=n，并在其上调用适合的统计函数。

amount = pd.Series([100, 90, 110, 150, 110, 130, 80, 90, 100, 150])
print(amount.rolling(3).sum())
"""
0      NaN      # NaN + NaN + 100
1      NaN      # NaN + 100 + 90
2    300.0      # 100 + 90 + 110
3    350.0      # 90 + 110 + 150
4    370.0      # 110 + 150 + 110
5    390.0      # 150 + 110 + 130
6    320.0      # 110 + 130 + 80
7    300.0      # 130 + 80 + 90
8    270.0      # 80 + 90 + 100
9    340.0      # 90 + 100 + 150
dtype: float64
"""

# 可以自定义函数
print(
    amount.rolling(3).apply(
        # 里面的参数x就是每个窗口里面的元素组成的Series对象
        lambda x: sum(x)
    )
)

"""
此外我们注意到，开始的两个元素为NaN，这是因为 rolling(3) 表示从当前位置往上筛选，总共筛选3个元素。
那么我们如果我们希望元素不够的时候有多少算多少，该怎么办呢？
比如：
    第一个窗口里面的元素之和就是第一个元素，
    第二个窗口里面的元素之和是第一个元素加上第二个元素。
"""
print(
    # min_periods 表示窗口的最小观测值
    amount.rolling(3, min_periods=1).apply(
        lambda x: sum(x)
    )
)
# 注意：min_periods必须小于等于窗口长度，否则报错。


"""
rolling里面还有一个center参数，默认为False。
我们知道 rolling(3) 表示从当前元素往上筛选，加上本身总共筛选3个。

但如果是将center指定为True的话，那么是以当前元素为中心，从两个方向上进行筛选。
比如rolling(3, center=True)，那么会往上选一个、往下选一个，再加上本身总共是3个。
"""
print(amount.rolling(3, center=True).sum())
"""
0      NaN    # NaN + 100 + 90
1    300.0    # 100 + 90 + 110
2    350.0    # 90 + 110 + 150
3    370.0    # 110 + 150 + 110
4    390.0    # 150 + 110 + 130
5    320.0    # 110 + 130 + 80
6    300.0    # 130 + 80 + 90
7    270.0    # 80 + 90 + 100
8    340.0    # 90 + 100 + 150
9      NaN    # 100 + 150 + NaN
dtype: float64
"""